package com.swang.pms.web.interceptor;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Date;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import com.swang.pms.model.annotation.PltLog;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.swang.pms.common.util.LoggerUtil;
import com.swang.pms.model.constants.CommonConstants;
import com.swang.pms.model.dto.PlfLogDto;
import com.swang.pms.model.entity.ManageUser;
import com.swang.pms.service.manage.impl.LogFactory;

@Aspect
@Component
public class LogAop {

    private static final Logger LOGGER = Logger.getLogger(LogAop.class);

    ThreadLocal<Long>           time   = new ThreadLocal<Long>();

    @Resource
    LogFactory                  logFactory;

    @Pointcut("@annotation(com.swang.pms.model.annotation.PltLog)")
    public void log() {
    }

    @Before("log()")
    public void beforeExec(JoinPoint joinPoint) {
        time.set(System.currentTimeMillis());
    }

    @After("log()")
    public void afterExec(JoinPoint joinPoint) {
        MethodSignature ms = (MethodSignature) joinPoint.getSignature();
        Method method = ms.getMethod();
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        ManageUser admin = (ManageUser) request.getSession().getAttribute(CommonConstants.SESSION_USER_KEY);
        if (admin == null || admin.getId() == null) {
            return;
        }
        try {
            StringBuffer stringBuffer = new StringBuffer("");
            for (int i = 0; i < joinPoint.getArgs().length; i++) {
                stringBuffer.append(joinPoint.getArgs()[i]);
            }
            writeLog(admin, joinPoint.getTarget().getClass().getSimpleName(), ms.getName(), request.getRequestURI(),
                    method.getAnnotation(PltLog.class).log(),
                    stringBuffer.toString().length() > 500 ? stringBuffer.toString().substring(0, 500) : stringBuffer.toString(),
                    getIpAddress(request), (int) (System.currentTimeMillis() - time.get()));
        } catch (IOException e) {
            LoggerUtil.error(e, LOGGER, "writeLog：", joinPoint);
        }
    }

    private void writeLog(ManageUser admin, String className, String methodName, String requestURI, String content, String requestParams,
                          String clientIp, int elapsedTime) {
        PlfLogDto log = new PlfLogDto();
        log.setClassName(className);
        log.setMethodName(methodName);
        log.setUrl(requestURI);
        log.setContent(content);
        log.setClientIp(clientIp);
        log.setRequestParams(requestParams);
        log.setElapsedTime(elapsedTime);
        log.setGmtCreate(new Date());
        log.setOperator(admin.getUserName());
        logFactory.addLog(log);
    }

    public final static String getIpAddress(HttpServletRequest request) throws IOException {
        String ip = processIp(request);
        if (ip != null && ip.length() > 15) {
            String[] ips = ip.split(",");
            for (int index = 0; index < ips.length; index++) {
                String strIp = (String) ips[index];
                if (!("unknown".equalsIgnoreCase(strIp))) {
                    ip = strIp;
                    break;
                }
            }
        }
        return ip;
    }

    public static String processIp(HttpServletRequest request) {
        String[] ipHeaders = { "X-Forwarded-For", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR" };
        String resultIp = null;
        for (int i = 0, n = ipHeaders.length; i < n; i++) {
            resultIp = request.getHeader(ipHeaders[i]);
            if (hasIp(resultIp)) {
                return resultIp;
            }
        }
        if (!hasIp(resultIp)) {
            return request.getRemoteAddr();
        } else {
            return "";
        }
    }

    private static boolean hasIp(String ip) {
        return !(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip));
    }

    private void info(JoinPoint joinPoint) {

    }

}
